package iosu.java.games.razer;

import iosu.java.games.razer.api.protocol.RazerProtocol;
import iosu.java.games.razer.api.protocol.RazerProtocolBinarySocket;
import iosu.java.games.razer.api.protocol.RazerProtocolMessage;

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;

import javax.management.InvalidApplicationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Esta clase implementa el hilo que llevara todas las comunicaciones
 * estara conectado al servidor, enviara los mensajes que le indique el cliente razer
 * y cuando reciba un mensaje, se lo enviara al cliente
 * De este modo el cliente no tiene que estar esperando a que el servidor le conteste
 * @author iosu
 *
 */
public class RazerClientNetworker implements Runnable{
    private static Logger logger;
    // en esta cola escribe el RazerClient y desde aqui solo leo, evio y espero respuesta
    private BlockingQueue<RazerProtocolMessage> messagesToSend;
    // cuando el servidor me conteste, escribo en esta cola. De el leera el RazerClient
    private BlockingQueue<RazerProtocolMessage> messagesToDispatch;
    private RazerProtocol razerprotocol;
    private boolean isConnected=false;
    
    static{
        logger= LoggerFactory.getLogger(RazerClientNetworker.class);
    }
    
    public RazerClientNetworker(RazerClient rc) throws IOException{
        logger.debug("Creado RazerClientNetworker asociado a {} en Thread: {}", rc.getIdcliente(), Thread.currentThread().getName());
        this.messagesToSend = rc.getSendQueue();
        this.messagesToDispatch = rc.getReadQueue();
        this.razerprotocol = new RazerProtocolBinarySocket(new Socket(rc.getServerIP(), rc.getServerPORT()));
        this.isConnected = true;
    }
    
    public boolean isConnected(){
    	return this.isConnected;
    }

    @Override
    public void run() {
        // aqui bucle infinito, leo de la cola de envio y mando los mensajes al servidor
        // y leo la respuesta y la dejo en la cola de recepcion
        // dependiendo del mensaje que haya enviado el cliente se quedara esperando respuesta o no
        // * para los CARUPDATEs no esperara respuesta, si la hay bien y si no ya la leera mas tarde
        while(true){
            // espero a que haya algo en messagesToSend
        	while(!messagesToSend.isEmpty()){
                try{
                    // envio el mensaje al servidor
                    RazerProtocolMessage m = messagesToSend.take();
                    this.razerprotocol.send(m);
//                    System.out.println("mensaje enviado..."+m);
                    // y espero su respuesta
                    m=RazerProtocolBinarySocket.decodeMessage(razerprotocol.receive().getMessageContent());
                    this.messagesToDispatch.add(m);
//                    System.out.println("respuesta recibida..."+m);
                }catch(IOException|InvalidApplicationException|InterruptedException e){
                    logger.error("error enviando mensaje",e);
                }
            }
        }
    }

}
